home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / comms_w / twswfwg.zip / DIS_PKT.ASM next >
Assembly Source File  |  1994-05-27  |  61KB  |  2,208 lines

  1.     TITLE    DIS_PKT
  2.  
  3. ; DIS_PKT.ASM - Adapter provides Packet Driver v1.11 interface over NDIS.
  4. ; Version 1.07  18 May 1991  by Joe R. Doupnik, Utah State Univ.
  5. ; Version 1.08  9 Aug 1991 by Dan Lanciani, ddl@harvard.harvard.edu
  6. ; Version 1.09  3 Nov 1991 by Joe R. Doupnik, Utah State Univ.
  7. ; Version X.10  6 Nov 1991 by Dan Lanciani, ddl@harvard.harvard.edu
  8. ; Version 1.10  5 Feb 1992 by Dan Lanciani, ddl@harvard.harvard.edu
  9. ; Version 1.11  31 Dec 1992 by Dan Lanciani, ddl@harvard.harvard.edu
  10. ; Copyright (C) 1988 - 1991 FTP Software, Inc.
  11. ;
  12. ; This unmodified source file and it's executable form may be used and
  13. ; redistributed freely.  The source may be modified, and the source or
  14. ; executable versions built from the modified source may be used and
  15. ; redistributed, provided that this notice and the copyright displayed by
  16. ; the exectuable remain intact, and provided that the executable displays
  17. ; an additional message indicating that it has been modified, and by whom.
  18. ;
  19. ; FTP Software Inc. releases this software "as is", with no express or
  20. ; implied warranty, including, but not limited to, the implied warranties
  21. ; of merchantability and fitness for a particular purpose.
  22. ;
  23. ; USE AT YOUR OWN RISK.
  24. ;
  25. ; Please send bug reports to ddl@harvard.harvard.edu or
  26. ;
  27. ; Dan Lanciani
  28. ; 185 Atlantic Road
  29. ; Gloucester, MA 01930
  30. ;
  31. ;
  32. ; To build, using Microsoft MASM 5 or later, LINK 3.64 or later, and EXE2BIN:
  33. ;
  34. ; masm dis_pkt;
  35. ; link dis_pkt;
  36. ; exe2bin dis_pkt.exe dis_pkt.dos
  37. ; del dis_pkt.exe
  38. ; del dis_pkt.obj
  39. ;
  40. ;
  41. ;What DIS_PKT.DOS does: It provides a Packet Driver
  42. ;interface to programs built to operate over Packet Drivers.  It talks
  43. ;to NDIS (3Com/Microsoft) instead of to a lan board directly.  It shares
  44. ;the board with NDIS users.  We call this a "shim", sitting between the
  45. ;normal applications program (NetWare shells, TCP/IP, etc) and the more
  46. ;hardware specific portions (NDIS in this case).
  47. ;
  48. ;    Packet Driver flavored applications    NDIS flavored applications
  49. ;        ||                    ||
  50. ;        -------------                ||
  51. ;        |  DIS_PKT  |                ||
  52. ;        -------------                ||
  53. ;        ||                    ||
  54. ;        ------------------------------------------
  55. ;        |           main module              |
  56. ;        |   NDIS    ........................      |
  57. ;        |        board specific driver(s)      |
  58. ;        -------------------------------------------
  59. ;                  ||
  60. ;            -------------------------
  61. ;            |    Ethernet board(s)    |
  62. ;            -------------------------
  63. ;                  ||
  64. ;        =========================================== Ethernet wire
  65. ;
  66. ;
  67. ;First sample PROTOCOL.INI file:
  68. ;
  69. ;[protocol manager]
  70. ;    drivername = PROTMAN$
  71. ;
  72. ;[pktdrv]            <-- name of this driver entry
  73. ;  drivername = pktdrv$        <-- formal driver name
  74. ;  bindings = wd8003xmac    <-- use your board's NDIS driver here
  75. ;  intvec = 0x60        <-- Packet Driver Int, 60h..7fh
  76. ;  chainvec = 0x66        <-- post-EOI processing interrupt
  77. ;  novell = y            <-- Optional, if present and y(es) then
  78. ;                    convert between old Novell 802.3 pkts
  79. ;                    on the wire and Type 8137 for the app.
  80. ;                    Omitting this line or using any other
  81. ;                    response turns off the conversion;
  82. ;                    default is no conversion.
  83. ;
  84. ;[attiso]
  85. ;  drivername = ATTISO$        <-- Another NDIS client
  86. ;  bindings = wd8003xmac    <-- bound to the same harware driver
  87. ;  nsess = 5
  88. ;  ncmds = 14
  89. ;  use_emm = n
  90. ;
  91. ;Western Digital EtherCard PLUS Family Adapter    <-- Ethernet board
  92. ;[wd8003xmac]                    <-- its ndis driver
  93. ;    drivername = MACWD$
  94. ;    irq = 7
  95. ;    ramaddress = 0xCA00
  96. ;    iobase = 0x280
  97. ;    receivebufsize = 1536    <-- make this a full Ethernet pkt
  98. ;
  99. ;
  100. ;
  101. ;
  102. ;Sample section of CONFIG.SYS (StarGROUP material is not required):
  103. ;
  104. ;device=c:\lanman\protman.sys /i:c:\lanman    <-- must be first
  105. ;device=c:\lanman\macwd.dos            <-- WD8003E driver
  106. ;device=c:\lanman\dis_pkt.dos            <-- Pkt Driver (this program)
  107. ;device=c:\lanman.dos\drivers\attload.dos /Y    <-- StarGROUP NDIS
  108. ;device=c:\lanman.dos\drivers\attiso\attiso.dos    <-- StarGROUP NDIS
  109. ;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys  <-- PC/TCP stuff
  110. ;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys  <-- etc
  111. ;
  112. ;
  113. ; A second, more elaborate example, with names easier to type.  We start with
  114. ;file PROTOCOL.INI.  Note that semicolons start comment lines.
  115. ;
  116. ;; This is a sample protocol.ini file listing three Ethernet boards:
  117. ;;    attcsma.dos is an AT&T StarLAN 10 EN100
  118. ;;    elnkii.dos  is a 3Com 3C503
  119. ;;    wd8003.dos  is a Western Digital WD8003E
  120. ;; Only one board will be selected but the other two are present.
  121. ;
  122. ;[protocol manager]
  123. ;    drivername = PROTMAN$
  124. ;
  125. ;; Packet Driver protocol users tie in here
  126. ;[pktdrv]
  127. ;    drivername = pktdrv$
  128. ;    bindings = attcsma
  129. ;;    bindings= elnkii
  130. ;;    bindings = wd8003
  131. ;    intvec = 0x60
  132. ;;    chainvec = 0x66
  133. ;    novell = no        ; do not convert packet types this time
  134. ;
  135. ;; AT&T StarGROUP protocol stack ties in here via name ATTISO$
  136. ;[attiso]
  137. ;    drivername = ATTISO$
  138. ;    bindings = attcsma
  139. ;;    bindings = elnkii
  140. ;;    bindings = wd8003
  141. ;    nsess = 5
  142. ;    ncmds = 14
  143. ;    use_emm = n
  144. ;
  145. ;;Western Digital EtherCard PLUS Family Adapter, WD8003E in this case
  146. ;[wd8003]
  147. ;    drivername = MACWD$
  148. ;    irq = 7
  149. ;    ramaddress = 0xCA00
  150. ;    iobase = 0x280
  151. ;    receivebufsize = 1536
  152. ;;    maxtransmits = 6
  153. ;;    receivebuffers = 6
  154. ;;    receivechains = 6
  155. ;
  156. ;; 3Com Etherlink II, 3C503
  157. ;[elnkii]
  158. ;    drivername = ELNKII$
  159. ;    ioaddress = 0x350
  160. ;    interrupt = 5
  161. ;    transceiver = onboard
  162. ;    maxtransmits = 12
  163. ;    xmitbufs = 1
  164. ;
  165. ;; AT&T StarLAN 10 EN100
  166. ;[attcsma]
  167. ;    drivername = ATTCSMA$
  168. ;    board_type = 2
  169. ;    irq = 2
  170. ;    ioaddr = 0x360
  171. ;    daram = 0xD000
  172. ;
  173. ;; End of file protocol.ini
  174. ;
  175. ;Fragment of config.sys for the second example.  Note three .dos board drivers.
  176. ;
  177. ;device=c:\system\ramdrive.sys 1024 512 128 /E
  178. ;device=c:\lanman\protman.sys /i:c:\lanman.dos\drivers\star10en
  179. ;device=c:\lanman\attcsma.dos
  180. ;device=c:\lanman\elnkii.sys
  181. ;device=c:\lanman\macwd.dos
  182. ;device=c:\lanman\dis_pkt.dos
  183. ;device=c:\lanman.dos\drivers\attload.dos /Y
  184. ;device=c:\lanman.dos\drivers\attiso\attiso.dos
  185. ;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys
  186. ;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys
  187. ;device=c:\qemm\loadhi.sys /r:4 c:\netdev.sys
  188. ;shell=c:\command.com  /p /e:800
  189. ;
  190. ;It is necessary to run NETBIND.EXE to get all this to be active.
  191. ;
  192.  
  193. ;
  194. ; Edit History
  195. ; 06-Jul-89    WJR    Changed interface flags in LDT to 2 per Norsk Data
  196. ;             (may make vector binding work).  Changed receive to
  197. ;             allocate buffer for frame size instead of lookahead
  198. ;             value.  (This will fail miserably if the frame size
  199. ;             is unknown at upcall time; such is life.) Changed
  200. ;             SetPacketFilter to use module ID instead of dummy.
  201. ; 11-Sep-89    jbvb    Clean up, add 1.09 functionality.
  202. ; 12-Sep-89    jbvb    Don't do interrupt if vector contents are 0.
  203. ; 14-Sep-89     wjr    Changed frame_rejected to frame_not_recognized to make
  204. ;             vectored operation work.  Changed send_pkt to use
  205. ;             drv_cct.mod_id.  Tried using 0 as protocol id in open
  206. ;             adapter call.  Changed device name to pktdrv$,
  207. ;             flushed open adapter not supported message.
  208. ; 15-Sep-89    wjr    Changed open adapter back to CS since 0 broke it.
  209. ; 24-Oct-89    wjr    Changed FRAME_NOT_RECOGNIZED from 4 to 3
  210. ; 07-Feb-90    wjr    Added push and pop SI to rcv_chn & rcv_lah.
  211. ; 02-Apr-90    wjr    Fixed xmt_chn to properly check for request queued
  212. ; 03-Apr-90    wjr    Given changed TCP, treat REQUEST_QUEUED as success.
  213. ; 06-Apr-90    jbvb    Update patch level to 2.
  214. ; 23-Apr-90    jbvb    Don't trash BP, free init code, fix comments.
  215. ; 25-Apr-90    jbvb    Support "extended" calls: get/set_rcv_mode,
  216. ;             get_statistics will suffice for LW.
  217. ; 26-Apr-90    jbvb    Support "match all" on typelen == 0.
  218. ; 05-Jun-90    jbvb    Fix stack bug in "match all" handling in access_type,
  219. ;             pass valid CX on 2nd receiver() upcall, version 5.
  220. ; 13-Jun-90    jbvb    Write basic set_address() code, but comment it out
  221. ;             because NDIS may require a CloseAdapter first in
  222. ;             order for it to work.  Not worth it to me.
  223. ; 27-Jul-90    jbvb    Copyright, build instructions, release v1.05.
  224. ; 24-Mar-91    jrd    Rewrite great chunks to straighen out stack and DS
  225. ;            addressing.  This now works with Novell IPX/NETn
  226. ;            and Netwatch (together as a matter of fact) and
  227. ;            with PC/TCP from FTP Inc. Version to 1.06.
  228. ;            Joe R. Doupnik, jrd@cc.usu.edu, Utah State Univ.
  229. ; 30-Mar-91    jrd    Allow 10 byte TYPE idents to pick out packets,
  230. ;            more cleanups, more needed.  Promiscuous mode put last.
  231. ;            Allow 20 handles.  Works fine with (NetWare+PC/TCP+
  232. ;            Netwatch) Pkt Drvr + Lan Man going simulanteously.
  233. ;            Works with Clarkson issued Packet Driver utilities.
  234. ; 18-May-91    jrd    Add filtering of packet addresses if running in
  235. ;            promiscuous mode, add get current Ethernet address
  236. ;            function to aid filtering, add receive mode indicator
  237. ;            for each handle, correct error in snd_def initing.
  238. ;            Correct problem with receive lookahead addressing.
  239. ;            Compensate for 3Com drivers not preserving regs.
  240. ;            Bump up NDIS tables to v2.  Dis_pkt version to 1.07.
  241. ; 09-Aug-91    ddl    802.5, 802.3 support; default binding; overwrite fix
  242. ; 03-Nov-91    jrd    Add keyword NOVELL to PROTOCOL.INI to convert between
  243. ;            old Novell 802.3 packets on the wire to 8137 for the
  244. ;            applications program.  Convert if the line is present
  245. ;            and the value is y(es).  Small cleanups.
  246. ; 06-Nov-91    ddl    Add general macro/routine in support of correct sync
  247. ;            calls to MAC.  Make send_pkt wait for completion.
  248. ;            Eliminate extra cs: prefixes and consolidate various
  249. ;            register/register and register/stack operations.  Use
  250. ;            mac_ds for all downcalls.  Add MAC open/close routines
  251. ;            for set_address and Token Ring all-frames mode.  Enable
  252. ;            PD set_address API.
  253. ; 08-Nov-91    ddl    Eliminate extra register saves and compares.  Absorb
  254. ;            set_packet_filter errors for Token Ring drivers in
  255. ;            all-frames mode.  Allow multiple handles with the
  256. ;            same type.  More cleanup.
  257. ; 09-Nov-91    ddl    Add deliver routine to handle multiple upcalls per
  258. ;            packet.  Replace broken packet filter code.  Various
  259. ;            code rewrites.  Punt blocking send_pkt for WD driver.
  260. ;            (The WD driver does not generate TransmitConfirms
  261. ;            within IndicationCompletes and will therefore cause
  262. ;            deadlock if a blocking send_pkt is attempted.)  This
  263. ;            is a real problem since PD semantics require that
  264. ;            buffer use is finished when send_pkt completes and
  265. ;            we cannot guarantee such.
  266. ; 10-Nov-91    ddl    Remove more unnecessary push/pop code.  Assume max
  267. ;            frame size on ReceiveLookahead with zero length.
  268. ;            Take advantage of SUCCESS = 0.
  269. ; 11-Nov-91    ddl    Move Novell code from pktfilter to deliver to avoid
  270. ;            overwriting card's buffers.
  271. ; 12-Nov-91    ddl    Simplify packet filter.
  272. ; 05-Feb-92    ddl    Fix the Novell bug I introduced...
  273. ; 31-Dec-92    ddl    Another try at sync sends & remove restrictions
  274. ;            on non-zero vector pointer.  The new scheme allows
  275. ;            you to specify the true hardware interrupt as
  276. ;            ``chainvec'' in which case dis_pkt does not (of
  277. ;            course) perform the int.  Someday we can get the
  278. ;            info from NDIS v2 MAC drivers but until then...
  279.  
  280.     PAGE ,80
  281.  
  282. EOL    equ    <13, 10, '$'>
  283. LF    =    10
  284. CR    =    13
  285. EOS    =    '$'
  286. DOS    equ    21h
  287. prstr    equ    9
  288. fopen    equ    3dh
  289. fclose    equ    3eh
  290. ioctl    equ    44h
  291.  
  292. MSG    MACRO    TEXT
  293.     push    dx            ;; save DX across call
  294.     push    ax
  295.     push    ds
  296.     mov    ax, cs
  297.     mov    ds, ax
  298.     mov    dx, offset TEXT        ;; point to message
  299.     mov    ah, prstr        ; display dollar terinated string
  300.     int    dos
  301.     pop    ds
  302.     pop    ax
  303.     pop    dx
  304.     ENDM
  305.  
  306. ; Issue a request to the MAC and wait for the result
  307. ;
  308. SYNCREQUEST MACRO
  309.     mov    req_con_flg, REQUEST_QUEUED
  310.     call    Request
  311.     call    req_wt
  312.     ENDM
  313.  
  314. ; DOS request header offsets
  315.  
  316. command    =    2
  317. status    =    3
  318. bpb    =    18
  319. end_off    =    14
  320. end_seg =    16
  321.  
  322. ; NDIS General Request codes
  323.  
  324. INIT_DIAG    equ    1
  325. READ_ERR_LOG    equ    2
  326. SET_STA_ADDR    equ    3
  327. OPEN_ADAPTER    equ    4
  328. CLOSE_ADAPTER    equ    5
  329. RESET_MAC    equ    6
  330. SET_PKT_FLT    equ    7
  331. ADD_MULT_ADDR    equ    8
  332. DEL_MULT_ADDR    equ    9
  333. UPDATE_STATS    equ    10
  334. CLEAR_STATS    equ    11
  335. INTERRUPT_ME    equ    12
  336. SET_FUNC_ADDR    equ    13
  337. SET_LOOKAHEAD    equ    14
  338.  
  339. ADDR_NONE    equ    0    ; NDIS Receiver modes: disabled
  340. ADDR_MULT    equ    1    ; Receive packets for my address & multicast
  341. ADDR_BRD    equ    2    ; Receive broadcast packets
  342. ADDR_PROM    equ    4    ; Receive all packets (promiscuous mode)
  343. ADDR_SRCRT    equ    8    ; Receive all source-routed packets
  344.  
  345. ; Protocol to MAC return codes
  346.  
  347. SUCCESS            equ    0
  348. REQUEST_QUEUED        equ    2
  349. FRAME_NOT_RECOGNIZED    equ    3
  350. INVALID_PARAMETER    equ    7
  351. NOT_SUPPORTED        equ    9
  352. GENERAL_FAILURE        equ    0FFH
  353.  
  354. ; NDIS-related structure definitions
  355.  
  356. cct_def    struc
  357.     dw    64        ; Size of common characteristics table (cct)
  358.     dw    0        ; Level of cct (zero this version)
  359.     dw    0        ; Level of service-specific subtables
  360.     db    2        ; Major module version (2 BCD digits)
  361.     db    0        ; Minor module version (2 BCD digits)
  362.     dd    2        ; Module function flags
  363.     db    'PKTDRV$', 9 dup (0) ; Module name, 16 byte ASCIIZ format
  364.     db    4        ; Protocol level at upper boundary of module
  365.     db    0        ; type of interface at upper module boundary
  366.     db    1        ; protocol level at lower boundary of module
  367.     db    1        ; type of interface at lower module boundary
  368. mod_id    dw    -1        ; module ID filled in by Protocol Manager
  369. mod_ds    dw    0        ; module DS
  370. system    dd    0        ; system request dispatch entry point
  371. sscp    dd    0        ; pointer to service-specific characteristics
  372. sssp    dd    0        ; pointer to service-specific status
  373. udtp    dd    0        ; pointer to upper dispatch table
  374. ldtp    dd    0        ; pointer to lower dispatch table
  375.     dd    0        ; reserved (must be NULL)
  376.     dd    0        ; reserved (must be NULL)
  377. cct_def    ends
  378.  
  379. ssc_def    struc
  380.     dw    96        ; length of MAC service-specific
  381.                 ; characteristics table (ssc)
  382. mtype    db    16 dup (0)    ; type name of MAC, ASCIIZ format
  383.     dw    0        ; length of station addresses in bytes
  384.     db    16 dup (0)    ; permanent station address
  385. cur_add    db    16 dup (0)    ; current station address
  386.     dd    0        ; current functional address of adapter
  387.     dd    0        ; multicast address list
  388.     dd    0        ; link speed
  389. svc_1    dw    0        ; service flags
  390. svc_2    dw    0        ; service flags
  391. maxfram    dw    0        ; max frame size both sent and recv
  392.     dd    0        ; total transmission buffer cap in driver
  393.     dw    0        ; transmission buffer allocation block size
  394.     dd    0        ; total reception buffer cap in driver
  395.     dw    0        ; reception buffer allocation block size
  396.     db    3 dup (0)    ; IEEE vendor code (OUI)
  397.     db    0        ; vendor adapter code
  398.     dd    0        ; vendor adapter description pointer
  399. mirq    dw    0        ; IRQ of adapter (NDIS v2)
  400.     dw    0        ; transmit queue depth (NDIS v2)
  401.     dw    0        ; number of data blocks in buffer desc
  402. ssc_def    ends
  403.  
  404. sss_def    struc
  405.     dw    0        ; length of status table
  406.     dd    0        ; date/time of last diagnostics
  407. lstatus    dd    0        ; MAC status
  408.     dw    0        ; current packet filter
  409.     dd    0        ; pointer to media specific statistics table
  410.     dd    0        ; date/time of last ClearStatistics call
  411. r_tot    dd    0        ; total frames received
  412. r_crc    dd    0        ; frames with CRC error
  413. rb_tot    dd    0        ; total bytes received
  414. r_drop    dd    0        ; frames discarded - no buffer space
  415. r_mult    dd    0        ; multicast frames received
  416. r_bro    dd    0        ; broadcast frames received
  417. r_err    dd    0        ; frames received with errors
  418. r_big    dd    0        ; frames exceeding maximum size
  419. r_runt    dd    0        ; frames smaller than minimum size
  420. rb_mul    dd    0        ; multicast bytes received
  421. rb_bro    dd    0        ; broadcast bytes received
  422. r_hwer    dd    0        ; frames discarded - hardware error
  423. x_tot    dd    0        ; total frames transmitted
  424. xb_tot    dd    0        ; total bytes transmitted
  425. x_mul    dd    0        ; multicast frames transmitted
  426. x_bro    dd    0        ; broadcast frames transmitted
  427. xb_bro    dd    0        ; broadcast bytes transmitted
  428. xb_mul    dd    0        ; multicast bytes transmitted
  429. x_tmo    dd    0        ; frames not transmitted - time-out
  430. x_hwer    dd    0        ; frames not transmitted - hardware error
  431. sss_def    ends
  432.  
  433. udt_def    struc            ; upper dispatch table
  434.     dd    0        ; back pointer to cct
  435. reqadd    dd    0        ; request address
  436. xchain    dd    0        ; TransmitChain address
  437.     dd    0        ; TransferData address
  438.     dd    0        ; ReceiveRelease address
  439. indon    dd    0        ; IndicationOn address
  440. indoff    dd    0        ; IndicationOff address
  441. udt_def    ends
  442.  
  443. ldt_def    struc            ; lower dispatch table
  444.     dd    0        ; back pointer to cct
  445.     dd    2        ; interface flags (2 means something)
  446.     dd    0        ; RequestConfirm address
  447.         dd    0        ; TransmitConfirm address
  448.        dd    0        ; ReceiveLookahead indication address
  449.     dd    0        ; IndicationComplete address
  450.     dd    0        ; ReceiveChain indication address
  451.     dd    0        ; status indication address
  452. ldt_def    ends
  453.  
  454. snd_def    struc            ; transmit buffer descriptor
  455.     dw    0        ; byte count of immediate data (always 0)
  456.     dd    0        ; address of immediate data
  457.     dw    1        ; count of data blocks (always 1)
  458.     db    0        ; pointer type (0 == physical)
  459.     db    0        ; reserved
  460. snd_len    dw    0        ; number of bytes to send
  461. snd_off    dw    0        ; offset of data to send
  462. snd_seg    dw    0        ; segment of data to send
  463. snd_def    ends
  464.  
  465. rcv_def    struc            ; receive buffer descriptor
  466.     dw    1        ; count of data blocks (always 1)
  467.     db    0        ; pointer type (0 == physical)
  468.     db    0        ; reserved
  469. rcv_len    dw    0        ; number of bytes to get
  470. rcv_off    dw    0        ; offset of data to get
  471. rcv_seg    dw    0        ; segment of data to get
  472. rcv_def    ends
  473.  
  474. req_def    struc            ; Request block - Protocol Manager primitives
  475. req_opc    dw    0        ; opcode for PM request
  476. req_sta    dw    0        ; status returned from request
  477. req_of1    dw    0        ; first parameter pointer
  478. req_sg1    dw    0
  479. req_of2    dw    0        ; second parameter pointer
  480. req_sg2    dw    0
  481. req_prm    dw    0        ; parameter word
  482. req_def    ends
  483.  
  484. bnd_def    struc            ; binding list
  485. bnd_cnt    dw    1        ; number of MACs to bind to -- 0 or 1
  486. bnd_nam    db    16 dup (0)    ; name of module to bind to
  487. bnd_def    ends
  488.  
  489.  
  490.     SUBTTL    Resident Data Area
  491.     PAGE
  492.  
  493. CSEG    SEGMENT PARA PUBLIC 'CODE'
  494.     assume    cs:CSEG, ds:CSEG, es:nothing
  495.  
  496. ; DEVICE HEADER - must be at offset zero within device driver
  497.     dd    -1        ; becomes pointer to next device header
  498.     dw    8000H        ; attribute (char device)
  499.     dw    offset strat    ; pointer to device strategy routine
  500.     dw    offset intr    ; pointer to device interrupt handler
  501.     db    "PKTDRV$ "    ; device driver name
  502. ; END OF DEVICE HEADER
  503.  
  504. mac_cctp    dd    0    ; address of MAC's cct table
  505. mac_ds        dw    0    ; DS register for MAC
  506.  
  507. drv_cct        cct_def    <>    ; Common Characteristics Table
  508. drv_ldt        ldt_def    <>    ; Lower Dispatch Table
  509. drv_snd        snd_def    <>    ; Argument blocks for NDIS TransmitChain,
  510. drv_rcv        rcv_def    <>    ;  TransferData,
  511. drv_bnd        bnd_def    <>    ;  and Bind (via DOS IOCTL)
  512. drv_req        req_def    <>    ; Argument block for general NDIS requests
  513. TransmitChain    dd    0        ; MAC entry point to send packet
  514. TransferData    dd    0        ; MAC entry point for data copy
  515. Request        dd    0        ; MAC entry point for requests
  516. ;ReceiveRelease    dd    0        ; MAC entry point (???not used???)
  517. IndicationOn    dd    0        ; MAC entries to control Indications
  518. IndicationOff    dd    0        ;  (upcalls) from NDIS
  519.  
  520. req_con_flg    dw    0        ; Completion status from NDIS upcall
  521. xmt_cmp        dw    0        ; TransmitChain result
  522.  
  523. init_flg    db    0        ; Non-zero if we've been initialized
  524. address        db    6 dup (0)    ; Current address from MAC
  525. novell        db    0        ; if non-zero convert between old
  526.                     ; Novell 802.3 interior to Type 8137
  527.                     ; Caller used 8137, wire gets 802.3
  528. nd_mode        dw    3        ; Current NDIS packet filter
  529.  
  530. ; Request Header (RH) address, saved here by "strategy" routine
  531.  
  532. req_hdr        label    dword
  533. req_off        dw    0
  534. req_seg        dw    0
  535.  
  536. ; Save the request header for use by the interrupt routine
  537.  
  538. strat    PROC    FAR
  539.     mov    word ptr cs:req_off, bx    ; offset
  540.     mov    word ptr cs:req_seg, es    ; segment
  541.     ret
  542. strat    ENDP
  543.  
  544.     EVEN                    ; Get into word alignment
  545.  
  546. ;;
  547. ;; Data for Packet Driver
  548. ;;
  549. BAD_HANDLE    equ 1    ; invalid handle number
  550. NO_CLASS    equ 2    ; no interfaces of this class found
  551. NO_TYPE        equ 3    ; no interfaces of specified type found
  552. NO_NUMBER    equ 4    ; no interfaces of specified number found
  553. BAD_TYPE    equ 5    ; bad packet type specified
  554. NO_MULTICAST    equ 6    ; this interface does not support multicast
  555. CANT_TERMINATE    equ 7    ; this packet driver cannot terminate
  556. BAD_MODE    equ 8    ; an invalid receiver mode was specified
  557. NO_SPACE    equ 9    ; operation failed because of insufficient space
  558. TYPE_INUSE    equ 10    ; type had previously been accessed and not released
  559. BAD_COMMAND    equ 11    ; the command was out of range or not implemented
  560. CANT_SEND    equ 12    ; the packet couldn't be sent (usually hardware error)
  561. CANT_SET    equ 13    ; The hardware address couldn't be changed
  562. BAD_ADDRESS    equ 14    ; Hardware address has bad length or format
  563. CANT_RESET    equ 15    ; Couldn't reset interface (more than 1 handle open)
  564.  
  565. PD_LEVEL    equ    6    ; Implementation level (basic, high perf, ext)
  566. ANY_TYPE    equ    0ffffh    ; Matches any if_type
  567. ETHERADDR_LEN    equ    6    ; Length of an Ethernet address
  568.  
  569. ; The connection arrays: types, and corresponding upcalls
  570.  
  571. PD_MAX_CONNS    equ    20    ; The maximum number of handles/Types that can
  572.                 ;  be registered at one time
  573. MAX_P_LEN    equ    10    ; max length of TYPE matching field, bytes
  574.  
  575. per_handle    struc            ; Packet Driver HANDLE structure
  576. pd_conn_used    db    0        ; non-zero if this handle is in use
  577. pd_conn_type    db    MAX_P_LEN dup(0) ; associated packet type
  578. pd_conn_type_len dw    0        ; associated packet type length
  579. pd_conn_rmode    dw    3        ; receive mode for this handle
  580. pd_conn_rcvr    dd    0        ; receiver handler address
  581. pd_conn_class    db    0        ; interface class
  582. per_handle    ends
  583.  
  584. handles        per_handle PD_MAX_CONNS dup(<>)
  585. end_handles    label    byte
  586.  
  587. if_class    db    1    ; Class 1 is Ethernet
  588. if_type        equ    57    ; NDIS to Packet Driver adapter
  589. pd_version    equ    11    ; Version
  590. pd_vector    dw    -1    ; Packet Driver vector to serve on
  591. pd_rcv_mode    dw    3    ; Default to rcv mode 3 (normal/bcast)
  592. pd_name        db    "MAC/DIS converter", 0
  593. matchoff    dw    12    ; offset to match bytes
  594. addroff        dw    0    ; offset to addresses
  595. multimask    db    1    ; multicast
  596.  
  597. ; Table re-maps (badly) NDIS modes to Packet Driver modes (in parentheses)
  598. ndis_mode    db  0    ; No packets (0 == illegal)
  599.         db  0    ; No packets (1 == receiver off)
  600.         db  1    ; Directed | Multicast (2 should be directed only)
  601.         db  3    ; Directed | Multicast | Broadcast
  602.             ; (3 should be directed | broadcast)
  603.         db  3    ; Directed | limited Multicast | Broadcast
  604.             ; (4 == directed | broadcast | limited multicast)
  605.         db  3    ; Directed | limited Multicast | Broadcast
  606.             ; (5 should be directed | broadcast | all multicast)
  607.         db  4    ; Promiscuous (6 == match all)
  608.  
  609. EVEN    ; Get into word alignment
  610.  
  611. ; struct param; Pointer to this returned by get_parameters()
  612.  
  613. pd_param  db    1        ; Major revision = 1
  614.       db    9        ; Minor revision = 9
  615.       db    14        ; Length of this structure = 14
  616.       db    ETHERADDR_LEN    ; MAC addr length
  617. mtu      dw    1514        ; MAC packet length
  618.       dw    0        ; No multicast support
  619.       dw    0        ; No promises re: back-to-back receives
  620.       dw    0        ; No promises re: back-to-back transmits
  621. param_int dw    0        ; Default to no interrupt on EOI
  622.  
  623. ; Pointer to this returned by get_statistics
  624.  
  625. pd_statistics struc
  626. pkt_in        dd    0    ; Total packets in
  627. pkt_out        dd    0    ; Total packets out
  628. bytes_in    dd    0    ; Total bytes received
  629. bytes_out    dd    0    ; Total bytes sent
  630. errs_in        dd    0    ; Total transmit errors
  631. errs_out    dd    0    ; Total receive errors
  632. pkts_lost    dd    0    ; Packets dropped - no buffer, out of resc
  633. pd_statistics ends
  634.  
  635. pd_stat        pd_statistics <>    ; An instance of the above
  636.  
  637. PUBLIC    driver_info, access_type, release_type, send_pkt, terminate
  638. PUBLIC    get_address, reset_interface, get_parameters, set_rcv_mode
  639. PUBLIC    get_rcv_mode, get_statistics, set_address
  640.  
  641. ; Normal (basic Packet Driver functions) Jump Table
  642.  
  643. pd_table dw    pd_none        ; No handler
  644.     dw    driver_info    ; 1
  645.     dw    access_type    ; 2
  646.     dw    release_type    ; 3
  647.     dw    send_pkt    ; 4
  648.     dw    terminate    ; 5
  649.     dw    get_address    ; 6
  650.     dw    reset_interface    ; 7
  651. pd_table_size    equ    ($-pd_table)/2
  652.  
  653. ; High Performance functions Jump Table
  654.  
  655. hp_table dw    get_parameters    ; 10
  656.     dw    pd_none        ; 11 (as_send_pkt not implemented)
  657. hp_table_size    equ    ($-hp_table)/2
  658.  
  659. ; Extended functions Jump Table
  660.  
  661. ext_table dw    set_rcv_mode    ; 20
  662.     dw    get_rcv_mode    ; 21
  663.     dw    pd_none        ; 22 (set_multicast_list not implemented)
  664.     dw    pd_none        ; 23 (get_multicast_list not implemented)
  665.     dw    get_statistics    ; 24
  666.     dw    set_address    ; 25
  667. ext_table_size    equ    ($-ext_table)/2
  668.  
  669. ;
  670. ; rcv_lah is the proc that handles ReceiveLookAhead upcalls from the MAC
  671. ;
  672. ; First, it determines if the packet is one that is wanted.  If so, it asks
  673. ; the appropriate application for a buffer.  If it gets one, it copies the
  674. ; data and makes the 2nd call to the application to post it complete.  If
  675. ; not, it returns SUCCESS to the DIS driver anyway.  It returns SUCCESS if
  676. ; if the packet was copied or FRAME_NOT_RECOGNIZED if it is not in the list
  677. ; of desired types.
  678. ;
  679. ;The stack coming into this call is:
  680. ;    dw    bp[20]        MACID
  681. ;    dw    bp[18]        framesize
  682. ;    dw    bp[16]        bytes available in buffer
  683. ;    dw    bp[14]        lookahead data address seg
  684. ;    dw    bp[12]        lookahead data address off
  685. ;    dd    bp[10]        indicate flag
  686. ;    dw    bp[6]        ds of called protocol mode (ME)
  687. ;
  688.  
  689. rcv_lah    PROC    FAR
  690.     push    bp
  691.     mov    bp, sp
  692.     push    si            ; -2[bp]
  693.     push    di            ; -4[bp]
  694.     push    ds            ; -6[bp]
  695.     sub    sp, 2            ; -8[bp] return count
  696.     mov    ax, cs            ; setup data segment
  697.     mov    ds, ax
  698.     cld
  699.  
  700.     cmp    word ptr 18[bp], 0    ; unknown frame size
  701.     jnz    lah_have_size
  702.     mov    ax, mtu
  703.     mov    18[bp], ax        ; try for max
  704. lah_have_size:
  705.     les    dx, 12[bp]
  706.     mov    bx, offset handles - size per_handle
  707.     call    pktfilter        ; apply packet filter
  708.     jnc    lah_have_buf        ; nc = we want this packet
  709.     mov    ax, FRAME_NOT_RECOGNIZED ; packet not accepted
  710.     jmp    lah_don
  711.  
  712. lah_have_buf:
  713.     push    bx
  714.     lea    ax, -8[bp]        ; get scratch location
  715.     push    ss            ;  to put bytes copied into
  716.     push    ax            ;  and push it
  717.     xor    ax, ax            ; Starting offset in frame
  718.     push    ax            ;  is always zero
  719. ;
  720. ; Set up recv table description
  721. ;
  722.     mov    ax, 18[bp]        ; Len of recv data
  723.     mov    drv_rcv.rcv_len, ax    ;  goes in argument descriptor
  724.     mov    drv_rcv.rcv_seg, es    ;  as does far address of
  725.     mov    drv_rcv.rcv_off, di    ;  receive buffer
  726.     push    ds            ; Push far pointer to
  727.     mov    ax, offset drv_rcv    ;  descriptor
  728.     push    ax
  729.     push    mac_ds            ; Push MAC's DS value
  730.     call    TransferData        ; Copy pkt to buf (pops args)
  731. ;
  732. ; Call Packet Driver receive routine again (AX = 1) to finish up
  733. ;
  734.     pop    bx            ; recover handle
  735.     lds    si, dword ptr drv_rcv.rcv_off
  736.     call    deliver            ; run all the upcalls
  737.     xor    ax, ax
  738. lah_don:add    sp, 2            ; local material
  739.     pop    ds
  740.     pop    di
  741.     pop    si
  742.     pop    bp
  743.     ret    16            ; Pop MAC's params off stack
  744. rcv_lah    ENDP
  745.  
  746. ;
  747. ; rcv_chn is the proc that handles ReceiveChain upcalls from the MAC
  748. ;
  749. ; First, it determines if the packet is one that is wanted.
  750. ; It returns success if the packet is ok or FRAME_NOT_RECOGNIZED if it is not
  751. ; in the list of currently open types.
  752. ;
  753. ; The stack coming into this call is:
  754. ;    dw    bp[20]        MACID
  755. ;    dw    bp[18]        framesize
  756. ;    dw    bp[16]        request handle
  757. ;    dw    bp[14]        receive-chain buf descriptor address seg
  758. ;    dw    bp[12]        receive-chain buf descriptor address off
  759. ;    dd    bp[8]        indicate flag addr
  760. ;    dw    bp[6]        DS of called protocol mode (ME)
  761. ;
  762. ; where receive-chain buffer descriptor format is
  763. ;    dw    rxdatacount    count of received data blocks, max of 8
  764. ;    dw    rxdatalen    length of a data block
  765. ;    dd    rxdataptr    seg:offset of a data block
  766.  
  767. rcv_chn    PROC    FAR
  768.     push    bp
  769.     mov    bp, sp
  770.     push    si            ; -2[bp]
  771.     push    di            ; -4[bp]
  772.     push    ds            ; -6[bp]
  773.  
  774.     mov    ax, cs            ; setup data segment (== CS)
  775.     mov    ds, ax
  776.     cld
  777.  
  778.     les    di, 12[bp]
  779.     les    dx, es:[di+4]        ; es:di is now the buffer pointer
  780.     mov    bx, offset handles - size per_handle
  781.     call    pktfilter        ; apply packet filter, return handle
  782.     jnc    chn_have_buf        ; nc = we want this packet
  783.     mov    ax, FRAME_NOT_RECOGNIZED ; packet not accepted
  784.     jmp    chn_don
  785.  
  786. chn_have_buf:
  787.     push    es            ; Save ES:DI (pointer) to pass
  788.     push    di            ;  back to receiver later
  789.     lds    si, 12[bp]        ; Addr of rcv descriptor
  790.     mov    cx, [si]        ; Get number of data blocks
  791.     add    si, 2            ;  & move to top of list
  792.  
  793. chn_dat:        ; Move data from next block into stack's buffer
  794.     push    cx
  795.     push    ds
  796.     push    si
  797.     mov    cx, [si]        ; Get byte count of block
  798.     add    si, 2
  799.     lds    si, [si]        ; Get far pointer to data
  800.     shr    cx, 1
  801.     jnc    rcvchn5            ; nc = even already
  802.     movsb                ; Move 1 byte if count is odd
  803. rcvchn5:rep    movsw            ; Use word mov for efficiency
  804.     pop    si            ; Go through rest of chain
  805.     add    si, 6
  806.     pop    ds
  807.     pop    cx
  808.     loop    chn_dat            ; For all blocks
  809. ;
  810. ; Call Packet Driver receive routine again to finish up
  811. ;
  812.     pop    si            ; DS:SI = buffer pointer
  813.     pop    ds
  814.     call    deliver            ; run all the upcalls
  815.     xor    ax, ax
  816. chn_don:pop    ds
  817.     pop    di
  818.     pop    si
  819.     pop    bp
  820.     ret    16            ; pop params off stack
  821. rcv_chn    ENDP
  822.  
  823. ; Worker for lookahead and receive_chain procedures above.  Checks PD handles
  824. ; for wanting this kind of packet.  Returns carry clear, BX = handle,
  825. ; and ES:DI = buffer if packet is wanted, else carry set to reject the packet.
  826. ; If the adapter is in promiscuous mode (and the handle is not) we make an
  827. ; attempt at software filtering.  This is intentionally incomplete:  clients
  828. ; will be subjected to multicast packets that they may not want if any
  829. ; other client asks the adapter to accept multicast packets.  Therefore,
  830. ; there is no point in trying to avoid this situation in promiscuous mode.
  831. ; Later might want to add full filtering for all modes.
  832. ;
  833. ; Note that search starts at the handle *following* BX.  Expects lookahead
  834. ; pointer in ES:DX and packet length in 18[bp].
  835. ;
  836. pktfproc proc    near
  837. nohnd:    stc
  838.     ret
  839.  
  840. pktfilter:add    bx, size per_handle    ; next entry
  841.     cmp    bx, offset end_handles
  842.     jnc    nohnd
  843.     cmp    [bx].pd_conn_used, 0    ; is handle in use?
  844.     jz    pktfilter
  845.     mov    cx, [bx].pd_conn_type_len ; number of bytes to match
  846.     jcxz    foundhnd
  847.     lea    si, [bx].pd_conn_type    ; TYPE wanted by this handle
  848.     mov    di, dx            ; es:di is lookahead data ptr
  849.     cmp    if_class, 3
  850.     jnz    norif
  851.     test    byte ptr es:8[di], 80h
  852.     jz    norif
  853.     mov     al, es:14[di]
  854.     and    ax, 1fh
  855.     add    di, ax
  856. norif:    add    di, matchoff
  857.     cmp    novell, 0
  858.     jz    compare
  859.     cmp    word ptr es:2[di], 0ffffh
  860.     jnz    compare
  861.     cmp    word ptr [si], 3781h
  862.     jnz    compare
  863.     cmp    cx, 2            ; paranoia
  864.     jnz    compare
  865.     mov    ax, es:[di]
  866.     xchg    ah, al
  867.     cmp    ax, 1501
  868.     jc    foundhnd
  869. compare:repz    cmpsb
  870.     jnz    pktfilter
  871.  
  872. foundhnd:cmp    pd_rcv_mode, 6        ; board in promiscuous mode
  873.     jnz    nofil
  874.     cmp    [bx].pd_conn_rmode, 6    ; but handle is not--filter
  875.     jz    nofil
  876.     mov    cx, ETHERADDR_LEN
  877.     mov    si, offset address    ; our address
  878.     mov    di, dx
  879.     add    di, addroff
  880.     mov    al, multimask        ; multicast/broadcast bit
  881.     test    es:[di], al
  882.     jnz    nofil
  883.     repe    cmpsb
  884.     jz    nofil
  885.     jmp    pktfilter
  886.  
  887. nofil:    mov    cx, 18[bp]        ; recover length
  888.     xor    ax, ax
  889.     push    es
  890.     push    dx
  891.     push    bp
  892.     push    bx
  893.     call    [bx].pd_conn_rcvr    ; ask for a buffer
  894.     cli
  895.     cld
  896.     pop    bx
  897.     pop    bp
  898.     pop    dx
  899.     mov    ax, es
  900.     or    ax, di
  901.     jnz    havebuf
  902.     pop    es
  903.     jmp    pktfilter        ; no luck--continue search
  904. havebuf:pop    ax
  905.     clc
  906.     ret
  907. pktfproc endp
  908.  
  909. ; Deliver data to all interested handles following BX, then to BX itself.
  910. ; Data to be delivered in DS:SI, length in 18[bp].
  911. ;
  912. deliver    proc    near
  913.     push    bx
  914.                     ; do old Novell 802.3 to Type 8137
  915.     cmp    cs:novell, 0        ; doing old Novell conversion?
  916.     je    deliver0        ; e = no
  917.     push    si
  918.     add    si, cs:matchoff
  919.     cmp    word ptr [si+2], 0ffffh ; have the bad DSAP/SSAP signature?
  920.     jne    noconv            ; ne = no
  921.     mov    ax, [si]        ; get length/Type field value
  922.     xchg    ah, al            ; low endian form
  923.     cmp    ax, 1501        ; size is larger than length?
  924.     jnc    noconv
  925.     mov    word ptr [si], 3781h    ; force in Novell Type 8137
  926. noconv:    pop    si
  927.                     ; end of Novell section
  928. deliver0:push    ds
  929.     push    si
  930.     mov    ax, ds
  931.     mov    es, ax
  932.     mov    dx, si
  933.     mov    ax, cs
  934.     mov    ds, ax
  935.     call    pktfilter        ; find next potential client
  936.     pop    si
  937.     pop    ds
  938.     mov    ax, 1
  939.     mov    cx, 18[bp]
  940.     jc    deliver2
  941.     push    ds
  942.     push    si
  943.     push    es
  944.     push    di
  945.     push    cx
  946.     shr    cx, 1
  947.     jnc    deliver1
  948.     movsb
  949. deliver1:rep    movsw            ; copy between clients
  950.     pop    cx
  951.     pop    si
  952.     pop    ds
  953.     push    bx
  954.     push    bp
  955.     call    cs:[bx].pd_conn_rcvr    ; "secondary" client
  956.     cli
  957.     cld
  958.     pop    bp
  959.     pop    bx
  960.     pop    si
  961.     pop    ds
  962.     jmp    short deliver0
  963. deliver2:pop    bx
  964.     call    cs:[bx].pd_conn_rcvr    ; run the final upcall
  965.     cld
  966.     ret
  967. deliver    endp
  968.  
  969. ;
  970. ; Services indication complete upcall
  971. ;
  972. ; Executes interrupt (returned by get_parameters()) to pass control to
  973. ; an application which wants to run after the EOI.
  974. ;
  975. ; NOTE: Interrupt number at label ind_int is over-written if a different
  976. ;    interrupt is configured in protocols.ini.
  977. ;
  978. ind_com    PROC    FAR            ; Indication_complete upcall
  979.     push    es
  980.     push    bx
  981.     mov    bx, cs:param_int    ; Get offset of vector
  982.     cmp    bx, 16
  983.     jc    ind_no_int
  984.         xor    ax, ax
  985.     mov    es, ax            ; Point ES at interrupt segment
  986.     shl    bx, 1            ; Multiply by 4 for memory offset
  987.     shl    bx, 1
  988.     cmp    word ptr es:[bx]+2, 0    ; Is there a segment there?
  989.     jne    ind_int            ; ne = yes
  990.     cmp    word ptr es:[bx], 0    ; Is there an offset there?
  991.     je    ind_no_int        ; no, no interrupt
  992. ind_int:                ; INT 65 overwritten if selected
  993.     INT    65h            ; Pass control to the application
  994.  
  995. ind_no_int:
  996.     pop    bx            ; Restore registers
  997.     pop    es
  998.     xor    ax, ax
  999.     ret    4
  1000. ind_com    ENDP
  1001.  
  1002. ;;;;;;;;;;;;;;;;;;;;;;;;; Packet Driver section
  1003. regs    struc                ; stack offsets of incoming regs
  1004.     _ES    dw    ?
  1005.     _DS    dw    ?
  1006.     _BP    dw    ?
  1007.     _DI    dw    ?
  1008.     _SI    dw    ?
  1009.     _DX    dw    ?
  1010.     _CX    dw    ?
  1011.     _BX    dw    ?
  1012.     _AX    dw    ?
  1013.     _IP    dw    ?
  1014.     _CS    dw    ?
  1015.     _F    dw    ?        ; flags, Carry flag is bit 0
  1016. regs    ends
  1017. bytes    struc                ; stack offsets of incoming regs
  1018.         dw    ?        ; es, ds, bp, di, si are 16 bits
  1019.         dw    ?
  1020.         dw    ?
  1021.         dw    ?
  1022.         dw    ?
  1023.     _DL    db    ?
  1024.     _DH    db    ?
  1025.     _CL    db    ?
  1026.     _CH    db    ?
  1027.     _BL    db    ?
  1028.     _BH    db    ?
  1029.     _AL    db    ?
  1030.     _AH    db    ?
  1031. bytes    ends
  1032.  
  1033. CY    equ    0001h            ; to set caller's carry bit
  1034.  
  1035. ;
  1036. ; Interrupt handler for the Packet Driver interface (protocol stack downcalls)
  1037. ;
  1038. ; NOTE: Leaves interrupts disabled on entry - code in access_type and
  1039. ;    release_type depends on this.  send_pkt enables interrupts for MAC.
  1040. ;
  1041.     PUBLIC    pd_isr
  1042. pd_isr    PROC    FAR
  1043.     jmp    short over    ; skip the string (this MUST be a 3 byte jmp)
  1044.     nop            ; make three bytes
  1045.           db    "PKT DRVR", 0    ; string to identify a packet driver
  1046. over:
  1047.     push    ax
  1048.     push    bx
  1049.     push    cx
  1050.     push    dx
  1051.     push    si
  1052.     push    di
  1053.     push    bp
  1054.     push    ds
  1055.     push    es
  1056.     cld
  1057.     push    cs            ;set up ds to this code segment
  1058.     pop    ds
  1059.  
  1060.     mov    bp, sp            ;we use bp to access the original regs
  1061.     and    _F[bp], not CY        ;start by clearing the carry flag
  1062.     mov    _DH[bp], 0        ; put no-error code in caller's DH
  1063.  
  1064.     cmp    ah, pd_table_size    ; AH too large?
  1065.     jae    highperf_table        ; ae = yes, try next set
  1066.                     ; Dispatch on AH using normal table
  1067.     mov    bl, ah            ; Get function code
  1068.     xor    bh, bh            ;  into a word register
  1069.     shl    bx, 1            ; index by words
  1070.     jmp    pd_table[bx]        ; and go
  1071.  
  1072. highperf_table:
  1073.     sub    ah, 10        ; Offset of 1st high-performance function
  1074.     jl    pd_none            ; l = ah is out of range
  1075.     cmp    ah, hp_table_size    ; is AH still in range?
  1076.     jae    xtend_table        ; ae = no, try next set
  1077.                 ; Dispatch on AH using high-performance table
  1078.     mov    bl, ah            ; Get function code
  1079.     xor    bh, bh            ;  into a word register
  1080.     shl    bx, 1            ; index by words
  1081.     jmp    hp_table[bx]        ; and go
  1082.  
  1083. xtend_table:
  1084.     sub    ah, 10            ; Offset of 1st extended function
  1085.     jl    pd_none            ; l = AH is not in range
  1086.     cmp    ah, ext_table_size     ; still in range?
  1087.     jae    pd_none            ; ae = no
  1088.                     ; Dispatch on AH using extended table
  1089.     mov    bl, ah            ; Get function code
  1090.     xor    bh, bh            ;  into a word register
  1091.     shl    bx, 1            ; index by words
  1092.     jmp    ext_table[bx]        ; and go
  1093.  
  1094. pd_none:
  1095.     mov    dh, BAD_COMMAND        ; set error code
  1096. err_ret:
  1097.     mov    _DH[bp], dh        ; put error code in caller's DH
  1098.     or    _F[bp], CY        ; set caller's carry flag
  1099. good_ret:                ; good return (carry clear)
  1100.     pop    es
  1101.     pop    ds
  1102.     pop    bp
  1103.     pop    di
  1104.     pop    si
  1105.     pop    dx
  1106.     pop    cx
  1107.     pop    bx
  1108.     pop    ax
  1109.     iret
  1110.  
  1111. ;
  1112. ; Checks the handle in BX.  If out of range or not valid cleans up the
  1113. ; stack and jumps directly to err_ret with a BAD_HANDLE error.  Assumes
  1114. ; called with DS pushed and a near call.  If handle is good, just returns.
  1115. ; BX is shifted one bit to the left.
  1116. ;
  1117.  
  1118. ; Bounds check on handle
  1119. chk_hdl    PROC     NEAR
  1120.     mov    bx, _BX[BP]        ; Handle
  1121.     cmp    bx, offset handles    ; start of handles area
  1122.     jb    chkhdl1            ; b = out of range
  1123.     cmp    bx, offset end_handles    ; end of handles area
  1124.     jae    chkhdl1            ; ae = above max table size
  1125.     cmp    [bx].pd_conn_used, 0    ; is handle used?
  1126.     je    chkhdl1            ; e = no, go bomb out
  1127.     ret                ; return BX as handle
  1128. chkhdl1:
  1129.     pop    ds            ;clear stack (was the return address)
  1130.     mov    dh, BAD_HANDLE        ;return BAD_HANDLE error
  1131.     jmp    err_ret
  1132. chk_hdl    ENDP
  1133.  
  1134. ; The following implement the individual Packet Driver commands, basic
  1135. ; functions first.
  1136. ;
  1137. ; Send a packet.
  1138. ; If Novell mode is active, user's buffer may be altered.  XXX
  1139. ;
  1140. send_pkt:mov    es, _DS[bp]        ; get ds of data block to es
  1141.     mov    ax, _CX[bp]
  1142.     mov    drv_snd.snd_len, ax
  1143.     mov    si, _SI[bp]
  1144.     push    drv_cct.mod_id        ; put our module id
  1145.     mov    ax, 1
  1146.     push    ax
  1147.             ; do conversion of Type 8137 to old Novell 802.3
  1148.     cmp    novell, 0        ; doing Novell packet conversion?
  1149.     je    send_pkt3        ; e = no
  1150.     cmp    word ptr es:[si+12], 3781h ; outgoing Novell Type 8137?
  1151.     jne    send_pkt3        ; ne = no
  1152.     mov    ax, es:[si+12+4]    ; get internal length indicator
  1153.     xchg    ah, al
  1154.     inc    ax            ; round up to an even length
  1155.     and    al, not 1
  1156.     xchg    ah, al
  1157.     mov    es:[si+12], ax        ; change packet Type field to length
  1158.  
  1159. send_pkt3:mov    drv_snd.snd_off, si    ; store offset of pkt buffer
  1160.     mov    drv_snd.snd_seg, es    ; store segment of pkt buffer
  1161.     mov    bx, offset drv_snd    ; get addr of xmit buff desc
  1162.     push    ds            ; store on stack
  1163.     push    bx
  1164.     push    mac_ds            ; MACID
  1165.     mov    xmt_cmp, REQUEST_QUEUED    ; set up for queued data
  1166.     call    TransmitChain        ; do downcall to NDIS
  1167.     sti                ; enable ints just to be sure
  1168.     xor    cx, cx
  1169. send_pkt6:or    ax, ax
  1170.     jz    send_pkt4
  1171.     cmp    ax, REQUEST_QUEUED    ; queued?
  1172.     jne    send_pkt5        ; ne = no
  1173.     mov    ax, xmt_cmp
  1174.     loop    send_pkt6        ; XXX waiting breaks WD driver
  1175. send_pkt4:jmp    good_ret
  1176.  
  1177. send_pkt5:mov    dh, CANT_SEND        ; trouble, fail
  1178.     jmp    err_ret
  1179.  
  1180.  
  1181. ;
  1182. ; Handle driver_info() downcall - return driver information.
  1183. ;
  1184. driver_info:
  1185.     mov    ch, if_class        ; CH is class
  1186.     xor    cl, cl            ; CL is interface number (always 0)
  1187.     mov    _BX[bp], pd_version
  1188.     mov    _CX[bp], cx
  1189.     mov    _DX[bp], if_type
  1190.     mov    _SI[bp], offset pd_name    ; ds:si is ptr to name
  1191.     mov    _DS[bp], ds
  1192.     mov    _AX[bp], PD_LEVEL
  1193.     jmp    good_ret
  1194.  
  1195. ;
  1196. ; Handle access_type() - sets up to handle an Ethernet packet type.
  1197. ;
  1198. ; NOTE:    Depends on entry with interrupts disabled for shared data locking.
  1199. ;
  1200. access_type_class:
  1201.     mov    dh, NO_CLASS
  1202.     jmp    err_ret
  1203.  
  1204.  
  1205. access_type_number:
  1206.     mov    dh, NO_NUMBER
  1207.     jmp    err_ret
  1208.  
  1209. access_type_bad:
  1210.     mov    dh, BAD_TYPE
  1211.     jmp    err_ret
  1212.  
  1213. access_type:
  1214.     mov    al, if_class
  1215.     cmp    _AL[bp], al        ; our class?
  1216.     jne    access_type_class    ; ne = no, fail
  1217. ;    cmp    _BX[bp], ANY_TYPE    ; generic type?
  1218. ;    je    access_type_1        ; e = yes
  1219. ;    cmp    _BX[bp], if_type    ; our type?
  1220. ;    je    access_type_1        ; e = yes
  1221. ;    mov    dh, NO_TYPE
  1222. ;    jmp    err_ret
  1223. ;access_type_1:
  1224.     cmp    _DL[bp], 0        ; our number?
  1225.     jne    access_type_number    ; ne = no
  1226.     cmp    _CX[bp], MAX_P_LEN    ; is the type length too long?
  1227.     ja    access_type_bad        ; a = yes, this can't be ours
  1228.  
  1229. ; look for a free handle
  1230.  
  1231.     mov    bx, offset handles    ; first handle
  1232. access_type_2:
  1233.     cmp    [bx].pd_conn_used, 0    ; is this handle in use?
  1234.     jz    access_type_3
  1235.     add    bx, (size per_handle)    ; go to the next handle
  1236.     cmp    bx, offset end_handles    ; examined all handles?
  1237.     jb    access_type_2        ; b = no, continue
  1238.     mov    dh, NO_SPACE
  1239.     jmp    err_ret
  1240.  
  1241. access_type_3:
  1242.     mov    [bx].pd_conn_used, 1    ; remember that we're using it
  1243.     mov    ax, _DI[bp]        ; get receiver address from ES:DI
  1244.     mov    word ptr [bx].pd_conn_rcvr, ax    ; offset part
  1245.     mov    ax, _ES[bp]
  1246.     mov    word ptr [bx].pd_conn_rcvr+2, ax ; segment part
  1247.  
  1248.     push    ds
  1249.     mov    ax, ds
  1250.     mov    es, ax
  1251.     mov    ds, _DS[bp]        ; remember their type
  1252.     mov    si, _SI[bp]
  1253.     mov    cx, _CX[bp]
  1254.     mov    es:[bx].pd_conn_type_len, cx    ; remember the TYPE length
  1255.     lea    di, [bx].pd_conn_type
  1256.     rep    movsb            ; copy TYPE field to match
  1257.     pop    ds
  1258.     mov    al, _AL[bp]        ; remember Class
  1259.     mov    [bx].pd_conn_class, al
  1260.     mov    [bx].pd_conn_rmode, 3
  1261.     mov    _AX[bp], bx        ; return handle in caller's AX
  1262.     jmp    good_ret
  1263. ;
  1264. ; Perform release_type() - forget the packet type/upcall/handle
  1265. ;
  1266. ; NOTE:    Depends on entry with interrupts disabled for shared data locking.
  1267. ;
  1268. release_type:
  1269.     call    chk_hdl            ; get handle, return here if ok
  1270.                     ; This is a critical region!!
  1271.     mov    [bx].pd_conn_used, 0    ; free handle-used indicator
  1272.     jmp    good_ret
  1273. ;
  1274. ; Perform terminate() - never actually do it.
  1275. ;
  1276. terminate:
  1277.     call    chk_hdl            ; check handle
  1278.     mov    dh, CANT_TERMINATE    ; Return error
  1279.     jmp    err_ret
  1280.  
  1281. ;
  1282. ; Perform get_address() - get the current Ethernet address of the interface
  1283. ;
  1284. get_address:
  1285.     cmp    _CX[bp], ETHERADDR_LEN    ; Make sure it's an ethernet address
  1286.     jc    get_address_err
  1287.     call    get_eaddr
  1288.     mov    di, _DI[bp]
  1289.     mov    es, _ES[bp]
  1290.     mov    si, offset address
  1291.     mov    cx, ETHERADDR_LEN
  1292.     rep    movsb
  1293.     mov    _CX[bp], ETHERADDR_LEN
  1294.     jmp    good_ret
  1295.  
  1296. get_address_err:
  1297.     mov    dh, NO_SPACE        ; hmmm, I suppose it's close enough
  1298.     jmp    err_ret
  1299.  
  1300. ; Return board's current Ethernet address in address (ETHERADDR_LEN bytes)
  1301. ; via NDIS information.
  1302. get_eaddr proc    near
  1303.     push    ds
  1304.     mov    di, cs
  1305.     mov    es, di
  1306.     mov    di, offset address
  1307.     lds    si, mac_cctp        ; get address of mac cct
  1308.     lds    si, sscp[si]        ; get address of mac ssc
  1309.     add    si, cur_add        ; mov to offset in structure
  1310.     mov    cx, ETHERADDR_LEN    ; get length
  1311.     cld
  1312.     rep     movsb            ; copy address
  1313.     pop    ds
  1314.     ret
  1315. get_eaddr endp
  1316.  
  1317. ;
  1318. ; Perform reset_interface() - this is ignored.
  1319. ;
  1320. reset_interface:
  1321.     call    chk_hdl            ; check handle
  1322.     jmp    good_ret        ; if the handle was good, call is good
  1323.  
  1324. ;
  1325. ; The following implement the High Performance functions
  1326. ;
  1327. ; get_parameters() - Return pointer to parameters structure in ES:DI
  1328. ;
  1329. get_parameters:
  1330.     mov    _ES[bp], cs        ; return struct adr in caller's ES:DI
  1331.     mov    _DI[bp], offset pd_param
  1332.     jmp    good_ret        ;  & pass it to caller
  1333.  
  1334. ;
  1335. ; as_send_pkt() - Not implemented.
  1336. ;
  1337. ;as_send_pkt:
  1338. ;    mov    dh, BAD_COMMAND
  1339. ;    jmp    err_ret
  1340.  
  1341. ;
  1342. ; The following implement the Extended functions
  1343. ;
  1344. ; set_rcv_mode translates the PDS mode to an NDIS Packet Filter.
  1345. ;
  1346. set_rcv_mode:
  1347.     call    chk_hdl            ; get handle, return here if ok
  1348.     mov    cx, _CX[bp]
  1349.     jcxz    set_rcv_mode_err    ; z = illegal receive mode, quit
  1350.     cmp    cx, 6            ; is mode legal?
  1351.     ja    set_rcv_mode_err    ; a = no, quit
  1352.     mov    bx, cx            ; Put it in an index register
  1353.     mov    bl, ndis_mode[bx]    ; and translate it for NDIS
  1354.     xor    bh, bh
  1355.     call    set_ndis_mode        ; Try to set it
  1356.     jz    set_rcv_mode_ok
  1357. set_rcv_mode_err:
  1358.     mov    dh, BAD_MODE        ; no, return error
  1359.     jmp    err_ret
  1360.  
  1361. set_rcv_mode_ok:
  1362.     mov    bx, _BX[bp]        ; get handle again
  1363.     mov    cx, _CX[bp]
  1364.     mov    [bx].pd_conn_rmode, cx    ; set receive mode in handle's struct
  1365.     mov    pd_rcv_mode, cx        ; save the mode we just set
  1366.     jmp    good_ret        ;  and return ok
  1367.  
  1368. ;
  1369. ; Return the current Packet Driver receive mode.
  1370. ;
  1371. get_rcv_mode:
  1372.     call    chk_hdl            ; get handle, return here if ok
  1373.     mov    ax, [bx].pd_conn_rmode    ; get mode for this handle
  1374.     mov    _AX[bp], ax
  1375.     jmp    good_ret        ; return it
  1376.  
  1377.  
  1378. get_statistics:
  1379.     les    si, mac_cctp        ; ES:SI == address of NDIS cct
  1380.     les    si, es:sssp[si]        ; ES:SI == address of NDIS sss
  1381.     mov    ax, es
  1382.     or    ax, ax            ; Is the segment non-zero?
  1383.     jnz    getsta1            ; nz = yes, accept it
  1384.     or    si, si            ; how about offset?
  1385.     jnz    getsta1            ; nz = ok
  1386.     mov    dh, BAD_COMMAND        ; If they don't implement it,
  1387.     jmp    err_ret            ;  neither do we
  1388.  
  1389. getsta1:mov    ax, cs
  1390.     mov    ds, ax
  1391.     mov    di, offset pd_stat    ; Get start of PD stats table
  1392.     cli                    ; Don't allow updates just now
  1393.     mov    ax, word ptr es:r_tot[si]    ; Copy total received frames
  1394.     mov    dx, word ptr es:r_tot+2[si]
  1395.     call    valchk
  1396.     mov    ax, word ptr es:x_tot[si]    ; Copy total xmitted frames
  1397.     mov    dx, word ptr es:x_tot+2[si]
  1398.     call    valchk
  1399.     mov    ax, word ptr es:rb_tot[si]    ; Copy total received bytes
  1400.     mov    dx, word ptr es:rb_tot+2[si]
  1401.     call    valchk
  1402.     mov    ax, word ptr es:xb_tot[si]    ; Copy total transmitted bytes
  1403.     mov    dx, word ptr es:xb_tot+2[si]
  1404.     call    valchk
  1405.     mov    ax, word ptr es:r_err[si]    ; Copy total receive errors
  1406.     mov    dx, word ptr es:r_err+2[si]
  1407.     call    valchk
  1408.     mov    ax, word ptr es:x_hwer[si]    ; Copy total transmit errors
  1409.     mov    dx, word ptr es:x_hwer+2[si]
  1410.     call    valchk
  1411.     mov    ax, word ptr es:r_drop[si]    ; Copy total receives dropped
  1412.     mov    dx, word ptr es:r_drop+2[si]
  1413.     call    valchk
  1414.     sti                    ; All done with shared data
  1415.     mov    _SI[bp], offset pd_stat      ; set caller's DS:SI to the
  1416.     mov    ax, cs            ; address of Packet Driver stats
  1417.     mov    _DS[bp], ax
  1418.     jmp    good_ret
  1419.  
  1420. ; Convert double word dx:ax from NDIS unknown value of (long) -1 to (long) 0,
  1421. ; store results in ds:[di, di+2], move di forward two words.
  1422. valchk    proc    near
  1423.     cmp    ax, -1            ; starting at -1 (NDIS, for unknown)?
  1424.     jne    valchkx            ; ne = no
  1425.     cmp    dx, -1            ; this part too
  1426.     jne    valchkx            ; ne = no
  1427.     xor    ax, ax            ; zero counters for zero based counts
  1428.     xor    dx, dx
  1429. valchkx:mov    [di], ax        ; store results locally
  1430.     mov    [di+2], dx
  1431.     add    di, 4            ; step to next storage double word
  1432.     ret
  1433. valchk    endp
  1434.  
  1435. ;
  1436. ; Perform set_address() - change physical address of the interface.
  1437. ;
  1438. set_address:
  1439.     cmp    _CX[bp], ETHERADDR_LEN    ; Make sure it's an ethernet address
  1440.     jne    set_address_err        ; Jump if bad length
  1441.     call    close_m
  1442.     push    drv_cct.mod_id        ; Make set station address call
  1443.     mov    ax, 1
  1444.     push    ax            ; Push request ID (0 to not conf)
  1445.     xor    ax, ax
  1446.     push    ax            ; Must be 0
  1447.     push    _ES[bp]            ; Push pointer to address to set
  1448.     push    _DI[bp]
  1449.     mov    ax, SET_STA_ADDR    ; SetStationAddress function code
  1450.     push    ax
  1451.     push    mac_ds
  1452.     SYNCREQUEST
  1453.     jnz    set_err
  1454.     call    open_m
  1455.     call    get_eaddr
  1456.     jmp    good_ret
  1457.  
  1458. set_err:
  1459.     call    open_m
  1460.     call    get_eaddr        ; just in case
  1461.     mov    dh, CANT_SET
  1462.     jmp    err_ret
  1463.  
  1464. set_address_err:
  1465.     mov    dh, BAD_ADDRESS        ; We didn't like the address
  1466.     jmp    err_ret
  1467.  
  1468. pd_isr    ENDP
  1469. ;;;;;; end of Packet Driver direct support procedures
  1470.  
  1471. ;
  1472. ; The following are upcalls from DIS:
  1473.  
  1474. ; RequestConfirm enters with stack of (after our push bp)
  1475. ;    dw    [BP+16]        ProtID
  1476. ;    dw    [BP+14]        MACID
  1477. ;    dw    [BP+12]        ReqHandle
  1478. ;    dw    [BP+10]        Status
  1479. ;    dw    [BP+8]        Request
  1480. ;    dw    [BP+6]        ProtDS (our DS)
  1481.  
  1482. req_con    PROC    FAR            ; Request Confirm
  1483.     push    bp
  1484.     mov    bp, sp
  1485.     mov    ax, [bp+10]        ; get NDIS status response
  1486.     mov    cs:req_con_flg, ax    ; store in local area
  1487.     pop    bp
  1488.     xor    ax, ax
  1489.     ret    12
  1490. req_con    ENDP
  1491.  
  1492. ; Wait for a (possibly) queued request to complete & return result.
  1493. ; Z flag is set if success.
  1494.  
  1495. req_wt    PROC    NEAR
  1496.     sti
  1497. req_wt1:cmp    ax, REQUEST_QUEUED
  1498.     jnz    req_wt2
  1499.     mov    ax, req_con_flg
  1500.     jmp    short req_wt1
  1501. req_wt2:or    ax, ax
  1502.     ret
  1503. req_wt    ENDP
  1504.  
  1505.  
  1506. ; TransmitConfirm enters with stack of (after our push bp)
  1507. ;    dw    [BP+14]        ProtID
  1508. ;    dw    [BP+12]        MACID
  1509. ;    dw    [BP+10]        ReqHandle
  1510. ;    dw    [BP+8]        Status
  1511. ;    dw    [BP+6]        ProtDS (our DS)
  1512.  
  1513. xmt_con    PROC    FAR            ; Transmit Confirm
  1514.     push    bp
  1515.     mov    bp, sp
  1516.     mov    ax, 8[bp]
  1517.     mov    cs:xmt_cmp, ax        ; moves the return code into static
  1518.     pop    bp
  1519.     xor    ax, ax
  1520.     ret    10
  1521. xmt_con    ENDP
  1522.  
  1523.  
  1524. sta_ind    PROC    FAR            ; Status handled, not used
  1525.     xor    ax, ax
  1526.     ret    12
  1527. sta_ind    ENDP
  1528.  
  1529.  
  1530. dis_pat    PROC    FAR            ; System entry point for pkt driver
  1531.     push    bp            ; Used only by initiate bind request
  1532.     mov    bp, sp
  1533.     cmp    word ptr 8[bp], 1    ; Is it initiate_bind?
  1534.     je    dispat1            ; e = yes
  1535.     mov    ax, GENERAL_FAILURE    ; NO: fail
  1536.     pop    bp
  1537.     ret    14
  1538.  
  1539. dispat1:push    ds            ; save stuff
  1540.     push    es
  1541.     push    bx
  1542.     push    cx
  1543.     push    si
  1544.     push    di
  1545.  
  1546.     mov    ax, cs            ; set up DS == CS
  1547.     mov    ds, ax
  1548.     les    bx, 12[bp]
  1549.     mov    word ptr mac_cctp, bx
  1550.     mov    word ptr mac_cctp + 2, es
  1551.  
  1552.     mov    ax, offset drv_cct    ; push pkt drv cct (our cct)
  1553.     push    ds
  1554.     push    ax
  1555.     mov    ax, offset mac_cctp    ; push addr for MAC's cct
  1556.     push    ds
  1557.     push    ax
  1558.     xor    ax, ax            ; pad parameter
  1559.     push    ax
  1560.     mov    ax, 2            ; Load Bind command code
  1561.     push    ax
  1562.     push    es:[bx].mod_ds
  1563.     call    dword ptr es:[bx].system ; call MAC's system entry point
  1564.     or    ax, ax
  1565.     jz    dispat2            ; z = Bind succeeded
  1566.     MSG    bad_bind        ; tell the user the bad news
  1567.     jmp    rtn_dis            ; Bind failed, fatal error
  1568.  
  1569. dispat2:
  1570.     call    sav_mac            ; Save MAC entry point addresses
  1571.     les    bx, mac_cctp        ; Check if OpenAdapter needed
  1572.     les    bx, es:[bx].sscp
  1573.  
  1574.     lea    di, [bx].mtype
  1575.     mov    si, offset t8023
  1576.     mov    cx, offset t8023e - offset t8023
  1577.     cld
  1578.     repe    cmpsb
  1579.     jz    is8023
  1580.     lea    di, [bx].mtype
  1581.     mov    si, offset t8025
  1582.     mov    cx, offset t8025e - offset t8025
  1583.     repe    cmpsb
  1584.     jz    is8025
  1585.     jmp    short gottype
  1586. is8023:    mov    if_class, 11
  1587.     mov    matchoff, 14
  1588.     jmp    short gottype
  1589. is8025:    mov    if_class, 3
  1590.     mov    matchoff, 14
  1591.     mov    addroff, 2
  1592.     mov    multimask, 80h
  1593.     mov    ax, es:[bx].maxfram
  1594.     mov    mtu, ax
  1595. ;    jmp    short gottype
  1596.  
  1597. gottype:call    open_m
  1598.     jz    open_ok1        ; skip to setting packet filter
  1599.  
  1600.     MSG    bad_open_adpt        ; Fatal error: open adapter failed
  1601.     jmp    rtn_dis
  1602.  
  1603. open_ok1:
  1604.     push    mac_ds
  1605.     call    IndicationOff
  1606.     push    mac_ds
  1607.     call    IndicationOn
  1608.     sti
  1609.  
  1610.     call    get_eaddr
  1611.     mov    bx, 3            ; Set default filter: Directed,
  1612.     call    set_ndis_mode        ;  Multicast & Broadcast (3)
  1613.     jz    set_vec
  1614.     MSG    bad_set_pkt        ; show an error and fail
  1615.     jmp    rtn_dis
  1616.  
  1617. ; Give warning if the Packet Driver vector is already in use but use anyway
  1618.  
  1619. set_vec:
  1620.     xor    ax, ax            ; Set ES to 0 to look in int tab
  1621.     mov    es, ax
  1622.     mov    bx, cs:pd_vector    ; Get vector and multiply by 4
  1623.     shl    bx, 1
  1624.     shl    bx, 1
  1625.     mov    es:[bx], offset pd_isr
  1626.     mov    es:2[bx], cs
  1627.     xor    ax, ax
  1628. rtn_dis:
  1629.     pop    di            ; all done
  1630.     pop    si
  1631.     pop    cx
  1632.     pop    bx
  1633.     pop    es
  1634.     pop    ds
  1635.     pop    bp
  1636.     ret    14
  1637. dis_pat    ENDP
  1638.  
  1639. ; Make the NDIS SetPktFilter call (both at bind and from set_rcv_mode)
  1640. ;
  1641. ; Arguments:
  1642. ;    BX    NDIS Packet filter to set (see DIS p 45 for bits)
  1643. ;         * 0 - directed and multicast
  1644. ;         * 1 - broadcast
  1645. ;           2 - promiscuous
  1646. ;           3 - any source routing packet
  1647. ;
  1648. ; Some Token Rind drivers work in all-frames mode (even though they reject
  1649. ; the set_packet_filter call) as long as the appropriate argument is passed
  1650. ; to open_adapter.  The set_packet_filter error is ignored here for such
  1651. ; cases.
  1652. ;
  1653. set_ndis_mode PROC NEAR
  1654.     mov    ax, nd_mode
  1655.     xor    ax, bx
  1656.     and    ax, 4            ; changing to/from promiscuous mode
  1657.     jz    set_ndis_mode1
  1658.     push    bx
  1659.     call    close_m
  1660.     pop    bx
  1661. set_ndis_mode1:
  1662.     mov    nd_mode, bx
  1663.     push    drv_cct.mod_id        ; make set packet filter call
  1664.     mov    ax, 1
  1665.     push    ax            ; unique handle (0 to not conf)
  1666.     push    bx            ; Push packet filter value
  1667.     xor    ax, ax
  1668.     push    ax            ; dd pad
  1669.     push    ax
  1670.     mov    ax, SET_PKT_FLT        ; SetPacketFilter command
  1671.     push    ax
  1672.     push    mac_ds
  1673.     SYNCREQUEST
  1674.     push    ax
  1675.     call    open_m
  1676.     pop    ax
  1677.     cmp    ax, INVALID_PARAMETER    ; Absorb error...
  1678.     jnz    set_ndis_mode2
  1679.     cmp    if_class, 3        ; for Token Ring...
  1680.     jnz    set_ndis_mode2
  1681.     test    nd_mode, 4        ; in promiscuous mode only.
  1682.     jz    set_ndis_mode2
  1683.     xor    ax, ax
  1684. set_ndis_mode2:
  1685.     or    ax, ax
  1686.     ret                ; NDIS return code is in AX
  1687. set_ndis_mode ENDP
  1688.  
  1689. ; Open the MAC if appropriate.  Pass flags for Token Ring all-frames
  1690. ; mode as necessary.
  1691. ;
  1692. open_m    PROC NEAR
  1693.     les    bx, mac_cctp
  1694.     les    bx, es:[bx].sscp
  1695.     test    es:[bx].svc_1, 0800h            ; supports open
  1696.     jz    open_m1
  1697.     les    bx, mac_cctp
  1698.     les    bx, es:[bx].sssp
  1699.     test    word ptr es:[bx].lstatus, 010h        ; already open
  1700.     jnz    open_m1
  1701.     push    drv_cct.mod_id
  1702.     mov    ax, 1
  1703.     push    ax
  1704.     xor    ax, ax
  1705.     cmp    if_class, 3                ; for Token Ring
  1706.     jnz    open_m2
  1707.     test    nd_mode, 4                ; in promiscuous mode
  1708.     jz    open_m2
  1709.     mov    ax, 6
  1710. open_m2:push    ax
  1711.     xor    ax, ax
  1712.     push    ax
  1713.     push    ax
  1714.     mov    ax, OPEN_ADAPTER
  1715.     push    ax
  1716.     push    mac_ds
  1717.     SYNCREQUEST
  1718.     ret
  1719. open_m1:xor    ax, ax
  1720.     ret
  1721. open_m    ENDP
  1722.  
  1723. ; Close the MAC if appropriate.
  1724. ;
  1725. close_m    PROC NEAR
  1726.     les    bx, mac_cctp
  1727.     les    bx, es:[bx].sscp
  1728.     test    es:[bx].svc_1, 0800h            ; supports open
  1729.     jz    close_m1
  1730.     les    bx, mac_cctp
  1731.     les    bx, es:[bx].sssp
  1732.     test    word ptr es:[bx].lstatus, 010h        ; not open
  1733.     jz    open_m1
  1734.  
  1735.     push    drv_cct.mod_id
  1736.     mov    ax, 1
  1737.     push    ax
  1738.     xor    ax, ax
  1739.     push    ax
  1740.     push    ax
  1741.     push    ax
  1742.     mov    ax, CLOSE_ADAPTER
  1743.     push    ax
  1744.     push    mac_ds
  1745.     SYNCREQUEST
  1746.     ret
  1747. close_m1:xor    ax, ax
  1748.     ret
  1749. close_m    ENDP
  1750.  
  1751. ;
  1752. ; Put MAC entry points into static locations - called at bind time.
  1753. ;
  1754. sav_mac    PROC    NEAR
  1755.     les    si, mac_cctp
  1756.     mov    ax, es:[si].mod_ds    ; save MAC ds
  1757.     mov    mac_ds, ax
  1758.     les    si, es:[si].udtp
  1759.  
  1760.     mov    bx, offset Request    ; save request entry point
  1761.     mov    ax, es:4[si]
  1762.     mov    [bx], ax
  1763.     mov    ax, es:6[si]
  1764.     mov    2[bx], ax
  1765.  
  1766.     mov    bx, offset TransmitChain ; save xmt block entry point
  1767.     mov    ax, es:8[si]
  1768.     mov    [bx], ax
  1769.     mov    ax, es:10[si]
  1770.     mov    2[bx], ax
  1771.  
  1772.     mov    bx, offset TransferData    ; save xfer data entry point
  1773.     mov    ax, es:12[si]
  1774.     mov    [bx], ax
  1775.     mov    ax, es:14[si]
  1776.     mov    2[bx], ax
  1777.  
  1778. ;    mov    bx, offset ReceiveRelease ; save recv rel entry point
  1779. ;    mov    ax, es:16[si]
  1780. ;    mov    [bx], ax
  1781. ;    mov    ax, es:18[si]
  1782. ;    mov    2[bx], ax
  1783.  
  1784.     mov    bx, offset IndicationOn    ; save ind on entry point
  1785.     mov    ax, es:20[si]
  1786.     mov    [bx], ax
  1787.     mov    ax, es:22[si]
  1788.     mov    2[bx], ax
  1789.  
  1790.     mov    bx, offset IndicationOff ; save ind off entry point
  1791.     mov    ax, es:24[si]
  1792.     mov    [bx], ax
  1793.     mov    ax, es:26[si]
  1794.     mov    2[bx], ax
  1795.     ret
  1796. sav_mac    ENDP
  1797.  
  1798. ; Message strings needed at bind time.
  1799.  
  1800. bad_open_adpt    db    "Adapter did not open", EOL
  1801. bad_set_pkt    db    "Set packet filter failed", EOL
  1802. bad_bind    db    7, "BIND failed", EOL
  1803. t8023        db    '802.3', 0
  1804. t8023e:
  1805. t8025        db    '802.5', 0
  1806. t8025e:
  1807.  
  1808. end_res:    ;;;; Currently not keeping init code in memory
  1809.  
  1810. ;
  1811. ; DOS device driver interrupt entry point.
  1812. ;
  1813. ; This is used to initialize module and read parameters from PROTOCOLS.INI
  1814. ; only, and frees itself after startup.  The NDIS bind takes place later,
  1815. ; via dis_pat and its friends above.
  1816. ;
  1817. intr    PROC    FAR
  1818.     push    es            ; save all registers
  1819.     push    ds
  1820.     push    si
  1821.     push    di
  1822.     push    dx
  1823.     push    cx
  1824.     push    bx
  1825.     push    ax
  1826.  
  1827.     mov    ax, cs            ; check to see if already initialized
  1828.     mov    ds, ax
  1829.     mov    al, init_flg        ; our init flag
  1830.     or    al, al            ; not inited yet (0)?
  1831.     jz    intr1            ; z = yes, init now
  1832.  
  1833.     mov    bx, req_off        ; already initialized - return
  1834.     mov    ds, req_seg        ;  with error
  1835.     mov    [bx].status, 810Ch
  1836.     jmp    rtn
  1837.  
  1838. intr1:    cli                ; not initialized - switch to new
  1839.     mov    si, ss            ;  stack and init
  1840.     mov    dx, sp
  1841.     mov    ax, cs
  1842.     mov    ss, ax
  1843.     mov    sp, offset new_stk    ; Need a big stack for this call
  1844.     sti                ; Critical region
  1845.     push    si            ; Save old SS
  1846.     push    dx            ;  and SP
  1847.     MSG    msg_copyright        ; Display copyright notice
  1848.     call    init            ; Init this driver
  1849.  
  1850.     mov    ax, cs            ; Set DS == CS
  1851.     mov    ds, ax
  1852.     mov    bx, req_off        ; Get request header ptr
  1853.     mov    es, req_seg
  1854.     mov    word ptr es:[bx].status, 0100h    ; Set return status ok
  1855.     mov    init_flg, 1        ; Note that we've initialized
  1856.     mov    ax, offset end_res    ; Set end of resident code
  1857.     mov    word ptr es:[bx].end_off, ax
  1858.     mov    ax, cs
  1859.     mov    es:[bx].end_seg, ax
  1860.  
  1861.     pop    di            ; Old SP
  1862.     pop    si            ;  and old SS
  1863.     cli                ; Critical region
  1864.     mov    ss, si            ; Change back to old stack
  1865.     mov    sp, di
  1866.     sti                ; End critical region
  1867. rtn:    pop    ax            ; All done
  1868.     pop    bx
  1869.     pop    cx
  1870.     pop    dx
  1871.     pop    di
  1872.     pop    si
  1873.     pop    ds
  1874.     pop    es
  1875.     ret
  1876. intr    ENDP
  1877.  
  1878.     db    512 dup (0)
  1879. new_stk    label    word        ; A stack for init to use
  1880.     db    4 dup (0)
  1881. fil_han    dw    0        ; File handle for init
  1882.  
  1883. ;
  1884. ; Initialize the converter module - read parameters from PROTOCOLS.INI.
  1885. ;
  1886. init    PROC    NEAR
  1887.     mov    ax, cs            ; open the Protocol Manager driver
  1888.     mov    ds, ax
  1889.     mov    ah, fopen              ; open file
  1890.     mov    al, 0C2h
  1891.     mov    dx, offset pm__nam    ; device name
  1892.     int    dos
  1893.     jnc    init1                  ; nc = success
  1894.     MSG    pro_no_open        ; error
  1895.     jmp    init_err
  1896.  
  1897. init1:    mov    fil_han, ax        ; file handle
  1898.     mov    bx, ax
  1899.     mov    ax, cs
  1900.     mov    ds, ax
  1901.     mov    drv_req.req_opc, 1    ; make GetProtocolManagerInfo call
  1902.     mov    drv_req.req_sta, -1    ; zero out return status
  1903.     mov    drv_req.req_of1, -1    ; NULL out pointers
  1904.     mov    drv_req.req_sg1, -1
  1905.     mov    drv_req.req_of2, -1    ; NULL out pointer 2
  1906.     mov    drv_req.req_sg2, -1
  1907.     mov    drv_req.req_prm, -1    ; zero out parameter word
  1908.  
  1909.     mov    ah, ioctl        ; IOCTL req
  1910.     mov    al, 02h            ; device input
  1911.     mov    dx, offset drv_req    ; pointer to buffer
  1912.     mov    cx, 14            ; size of buffer
  1913.     int    dos            ; call DOS
  1914.     jnc      init2            ; nc = success
  1915.     MSG    pro_bad_gpm        ; Error: print msg & bomb
  1916.     jmp    init_err
  1917.  
  1918. init2:    mov    ax, cs            ; restore ds
  1919.     mov    ds, ax
  1920.  
  1921.     mov    ax, offset pro_nam    ; Get name of module to bind to,
  1922.     push    ax            ;  returned by get_pro in ES:DI
  1923.     mov    ax, pro_nam_len
  1924.     push    ax
  1925.     mov    ax, offset pro_bnd_to
  1926.     push    ax
  1927.     mov    ax, pro_bnd_to_len
  1928.     push    ax
  1929.     xor    ax, ax
  1930.     push    ax
  1931.     call    get_pro            ; Try to find the token we want
  1932.     or    di, di            ; Was it there?
  1933.     jnz    init4            ; nz = yes, parse it
  1934.     mov    drv_bnd.bnd_cnt, 0    ; else say nothing bound
  1935.     jmp    short init45
  1936.  
  1937. init4:    push    ds            ; Save name in bindings structure
  1938.     push    ds            ; currently allowed to bind to only
  1939.     push    es            ;  one MAC
  1940.     pop    ds
  1941.     pop    es
  1942.     mov    si, di
  1943.     mov    di, offset drv_bnd.bnd_nam
  1944.     mov    cx, -2[si]
  1945.     cld
  1946.     rep    movsb
  1947.     pop    ds
  1948.  
  1949. init45:    mov    ax, offset pro_nam    ; Get Packet Driver vector to use
  1950.     push    ax
  1951.     mov    ax, pro_nam_len
  1952.     push    ax
  1953.     mov    ax, offset pro_prm_vec    ; "INTVEC" keyword
  1954.     push    ax
  1955.     mov    ax, pro_prm_vec_len
  1956.     push    ax
  1957.     xor    ax, ax
  1958.     push    ax
  1959.     call    get_pro            ; Go look for the token
  1960.     or    di, di            ; Was the token found?
  1961.     jnz    init5            ; nz = yes
  1962.     MSG    vec_not_spc        ; abort if not found
  1963.     jmp    init_err
  1964.  
  1965. init5:    mov    dx, es:[di]        ; check that vector is in range
  1966.     cmp    dx, 80h            ; 0x80 is high limit
  1967.     jge    bad_vec2
  1968.     cmp    dx, 60h            ; 0x60 is low limit
  1969.     jl    bad_vec2
  1970.     mov    pd_vector, dx        ; Save value for bind time
  1971.     jmp    short init6        ; Go on to EOI interrupt
  1972.  
  1973. bad_vec2:
  1974.     MSG    msg_bad_vec        ; Abort if out of range
  1975.     jmp    init_err
  1976.  
  1977. init6:    mov    ax, offset pro_nam    ; Get EOI interrupt (if any)
  1978.     push    ax
  1979.     mov    ax, pro_nam_len
  1980.     push    ax
  1981.     mov    ax, offset pro_daisy_vec ; "CHAINVEC" key word
  1982.     push    ax
  1983.     mov    ax, pro_daisy_len
  1984.     push    ax
  1985.     xor    ax, ax
  1986.     push    ax
  1987.     call    get_pro            ; Try to find the token
  1988.     or    di, di
  1989.     jz    init7            ; z = no interrupt
  1990.  
  1991.     mov    dx, es:[di]        ; Check that interrupt is ok
  1992.     mov    byte ptr ind_int+1, dl    ; Modify the code
  1993.     mov    param_int, dx        ; Save interrupt number
  1994.  
  1995. init7:    mov    ax, offset pro_nam    ; Get old Novell 802.3 keyword
  1996.     push    ax
  1997.     mov    ax, pro_nam_len
  1998.     push    ax
  1999.     mov    ax, offset pro_novell    ; "NOVELL" key word
  2000.     push    ax
  2001.     mov    ax, pro_nov_len
  2002.     push    ax
  2003.     xor    ax, ax
  2004.     push    ax
  2005.     mov    novell, 0        ; assume no token
  2006.     call    get_pro            ; Try to find the token
  2007.     or    di, di
  2008.     jz    init8            ; z = no token
  2009.     mov    dx, es:[di]        ; get the token's value
  2010.     and    dl, not 20h        ; to upper case
  2011.     cmp    dl, 'Y'            ; "yes"?
  2012.     jne    init8            ; ne = no conversion
  2013.     mov    novell, 1        ; set flag
  2014.     MSG    novmsg            ; tell the user about conversion
  2015.  
  2016. init8:    call    pkt_ptr            ; Initialize the LDT and CCT pointers
  2017.     mov    ax, cs
  2018.     mov    ds, ax
  2019.     mov    drv_req.req_opc, 2    ; RegisterModule call
  2020.     mov    drv_req.req_sta, 0    ; zero out return status
  2021.     mov    drv_req.req_of1, offset drv_cct ; cct pointer
  2022.     mov    drv_req.req_sg1, ax
  2023.     mov    drv_req.req_of2, offset drv_bnd
  2024.     mov    drv_req.req_sg2, ax
  2025.     mov    drv_req.req_prm, 0    ; zero out parameter word
  2026.     mov    ah, ioctl        ; IOCTL call
  2027.     mov    al, 2
  2028.     mov    dx, offset drv_req
  2029.     mov    cx, 14
  2030.     mov    bx, fil_han
  2031.     int    dos
  2032.     cmp    drv_req.req_sta, SUCCESS
  2033.     je    init9            ; e = success
  2034.     MSG    reg_mod_nok
  2035.     jmp    init_err
  2036.  
  2037. init9:    mov    bx, fil_han        ; Close protman device
  2038.     mov    ah, fclose
  2039.     int    dos
  2040.     jc    init10            ; c = failure
  2041.     xor    ax, ax            ; Indicate success
  2042.     ret                ;  & do normal return
  2043.  
  2044. init10:    MSG    msg_err_clo        ; close failed, quite unlikely
  2045.     jmp    init_err
  2046.  
  2047. init_err:mov    ax, 1            ; error return
  2048.     ret
  2049. init    ENDP
  2050.  
  2051. ; get_pro returns a pointer to the keyword entry from GPMI call
  2052. ;    12[bp] is a pointer to module name
  2053. ;    10[bp] is length of module name
  2054. ;    8[bp] is a pointer to keyword name
  2055. ;    6[bp] is length of keyword name
  2056. ;    4[bp] is number of parameter wanted from specified keyword
  2057. ;
  2058. ; returns
  2059. ;    es:bx is pointer to param
  2060. ;    ax zero for ok and !0 for not found
  2061. ;
  2062. get_pro    PROC    NEAR
  2063.     push    bp
  2064.     mov    bp, sp
  2065.     push    ds
  2066.     push    bx
  2067.     push    si
  2068.     lds    bx, dword ptr drv_req.req_of1    ; ConMemIma pointer
  2069.  
  2070.     mov    ax, cs                ; find module name
  2071.     mov    es, ax
  2072. getpro1:mov    ax, ds                ; quit if pointer NULL (eol)
  2073.     or    ax, ax
  2074.     jz    err_get_pro            ; z = error
  2075.     mov    di, 12[bp]            ; module name
  2076.     mov    si, bx                ; set up to point name
  2077.     add    si, 8
  2078.     mov    cx, 10[bp]            ; module name length
  2079.     cld
  2080.     repe    cmpsb                ; right module name?
  2081.     je    pro_fnd                ; e = module name found
  2082.     lds    bx, dword ptr [bx]        ; not found-load next in chain
  2083.     jmp    short getpro1
  2084.  
  2085. pro_fnd:
  2086.     add    bx, 24                ; offset of parameter pointers
  2087. getpro2:
  2088.     mov    ax, ds
  2089.     or    ax, ax
  2090.     jz    err_get_pro
  2091.     mov    di, 8[bp]            ; parameter name
  2092.     mov    cx, 6[bp]            ; parameter name length
  2093.     mov    si, bx
  2094.     add    si, 8
  2095.     cld
  2096.     repe    cmpsb
  2097.     je    key_fnd                ; e = parameter found
  2098.     lds    bx, dword ptr [bx]        ; not found-load next in chain
  2099.     jmp    short getpro2
  2100. key_fnd:
  2101.     add    bx, 24                ; offset of values
  2102.     mov    cx, 4[bp]            ; check if enough values are
  2103.     cmp    cx, [bx]            ; here
  2104.     jge    err_get_pro
  2105.     add    bx, 2                ; position to the value
  2106.     jcxz    prm_fnd                ; may be either char string
  2107. getpro3:                    ;  or number depending on type
  2108.     add    bx, 2
  2109.     add    bx, [bx]
  2110.     add    bx, 2
  2111.     loop    getpro3
  2112. prm_fnd:
  2113.     mov    si, bx                ; set es:di to point to value
  2114.     add    si, 4
  2115.     mov    cx, 2[bx]
  2116.     mov    ax, ds
  2117.     mov    es, ax
  2118.     mov    di, si
  2119.     jmp    short getpro4
  2120. err_get_pro:
  2121. ;    MSG    pro_not_fnd            ; error return
  2122.     xor    ax, ax
  2123.     mov    es, ax
  2124.     mov    di, ax
  2125. getpro4:
  2126.     pop    si                ; common return
  2127.     pop    bx
  2128.     pop    ds
  2129.     pop    bp
  2130.     ret    10
  2131. get_pro    ENDP
  2132.  
  2133.  
  2134. pkt_ptr    PROC    NEAR                ; Set up pointers in Packet
  2135.     mov    ax, cs                ; Driver ldt and cct
  2136.     mov    ds, ax                ;  Note:most of this could
  2137.     mov    bx, offset drv_ldt        ;  (should) be done statically
  2138.     mov    word ptr [bx], offset drv_cct    ; driver's cct back pointer
  2139.     mov    2[bx], ax
  2140.     add    bx, 8                ; skip int flgs
  2141.     mov    [bx], offset req_con        ; RequestConfirm address
  2142.     mov    2[bx], ax
  2143.     mov    4[bx], offset xmt_con        ; TransmitConfirm address
  2144.     mov    6[bx], ax
  2145.     mov    8[bx], offset rcv_lah        ; ReceiveLookahead indication
  2146.     mov    10[bx], ax
  2147.     mov    12[bx], offset ind_com        ; IndicationComplete address
  2148.     mov    14[bx], ax
  2149.     mov    16[bx], offset rcv_chn        ; ReceiveChain indication add
  2150.     mov    18[bx], ax
  2151.     mov    20[bx], offset sta_ind        ; status indication address
  2152.     mov    22[bx], ax
  2153.  
  2154.     mov    bx, offset drv_cct.ldtp        ; set up point to drv ldt
  2155.     mov    word ptr [bx], offset drv_ldt
  2156.     mov    2[bx], ax
  2157. ;
  2158. ;set up pointers in pkt driver cct
  2159. ;    only doing lower dispatch table, all other left NULL
  2160. ;    hopefully this will work
  2161. ;
  2162.     mov    drv_cct.mod_id, -1
  2163.     mov    drv_cct.mod_ds, ax
  2164.     mov    bx, offset drv_cct.system
  2165.     mov    [bx], offset dis_pat        ; drv system func entry point
  2166.     mov    2[bx], ax            ; drv ds
  2167.     mov    word ptr 16[bx], offset drv_ldt    ; ptr to ldt
  2168.     mov    18[bx], ax
  2169.     ret
  2170. pkt_ptr    ENDP
  2171.  
  2172. ; Text messages that can be flushed after startup but before bind.
  2173.  
  2174. msg_no_vect    db    "Vector not specified", EOL
  2175. msg_bad_vec    db    "Invalid vector (must be 60h-7Fh)", EOL
  2176. msg_err_clo    db    "Error closing MAC driver", EOL
  2177. msg_copyright    db     "MAC/DIS to Packet Driver converter loaded."
  2178.         db    " Version 1.11", CR, LF
  2179.         db     "Copyright 1991 FTP Software, Inc.  All rights "
  2180.         db    "reserved.", cr, lf
  2181.         db    " v1.07 by Joe R. Doupnik, jrd@cc.usu.edu, "
  2182.         db    "Utah State Univ, 18 May 1991", cr, lf
  2183.         db    " v1.09 by Joe R. Doupnik, jrd@cc.usu.edu, "
  2184.         db    "Utah State Univ, 3 Nov 1991", cr, lf
  2185.         db    " v1.08, v1.10, v1.11 by"
  2186.         db    " Dan Lanciani, ddl@harvard.edu", EOL
  2187. pm__nam        db    "protman$", 0
  2188. pro_no_open    db    "Protocol Manager not present", EOL
  2189. pro_bad_gpm    db    "GetProtocolManagerInfo call failed", EOL
  2190. pro_nam        db    "PKTDRV", 0
  2191. pro_nam_len    equ    $ - pro_nam
  2192. pro_prm_vec    db    "INTVEC", 0
  2193. pro_prm_vec_len    equ    $ - pro_prm_vec
  2194. pro_daisy_vec    db    "CHAINVEC", 0
  2195. pro_daisy_len    equ    $ - pro_daisy_vec
  2196. pro_prm_nok    db    "SINTVECXX", 0
  2197. pro_prm_nok_len    equ    $ - pro_prm_nok
  2198. pro_bnd_to    db    "BINDINGS", 0
  2199. pro_bnd_to_len    equ    $ - pro_bnd_to
  2200. pro_novell    db    "NOVELL", 0
  2201. pro_nov_len    equ    $ - pro_novell
  2202. novmsg        db    "Using OLD NOVELL 802.3 packets on the wire", EOL
  2203. vec_not_spc    db    "Interrupt vector for Packet Driver not specifed"
  2204.         db    " in PROTOCOL.INI", EOL
  2205. reg_mod_nok    db    "Register module call failed", EOL
  2206. CSEG    ends
  2207.     end
  2208.